package com.lsh.ofc.worker.task;

import com.lsh.base.common.exception.BusinessException;
import com.lsh.base.common.model.CommonResult;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.OfcTaskStatus;
import com.lsh.ofc.core.enums.OfcTaskType;
import com.lsh.ofc.core.service.OfcOrderService;
import com.lsh.ofc.core.service.OfcSoService;
import com.lsh.ofc.core.service.SupplierConfigService;
import com.lsh.ofc.proxy.service.OpenApiServiceProxy;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

@Component
public class PushSoToCooperationPartnerJob extends AbstractOfcTaskJob {

    @Resource
    private OfcSoService soService;

    @Resource
    private OfcOrderService orderService;

    @Resource
    private OpenApiServiceProxy proxy;

    @Resource
    private SupplierConfigService supplierConfigs;

    private static final int FETCH_SIZE = 100;

    @Override
    protected OfcTaskType getFetchTaskType() {
        return OfcTaskType.SO_PUSH_ATP_API;
    }

    @Override
    protected int processTask(OfcTask task) throws BusinessException {
        try {
            OfcSoHead so = findSo(task.getRefId().toString());
            boolean success = proxy.createSalesOrder(buildRequestBaseOnSo(so), buildHeaders(so));
            return success ? 1 : -1;
        } catch (BusinessException e) {
            logger.error(e.toString(), e);
        }
        return -1;
    }

    private OfcSoHead findSo(String id) {
        OfcSoHead filter = new OfcSoHead();
        filter.setSoBillCode(id);
        OfcSoHead so = soService.findOne(filter, true);
        if (so == null) {
            throw new BusinessException(CommonResult.ERROR, "can not find so by bill code " + id);
        }
        return so;
    }

    private OfcSupplier findFulfillConfig(OfcSoHead so) {
        OfcSupplier supplier = supplierConfigs.findSupplier(so.getSupplierId(), so.getSupplierCode(), so.getSupplierGroup(), so.getSupplierOrg(), so.getRegionCode());
        if (supplier == null) {
            throw new BusinessException(CommonResult.ERROR, "can not find supplier by so " + so.getSoBillCode());
        }
        Map<String, Object> fulfillConfig = supplier.fulfillConfig();
        if (MapUtils.isEmpty(fulfillConfig)) {
            throw new BusinessException(CommonResult.ERROR, "find empty fulfill config by so " + so.getSoBillCode());
        }
        return supplier;
    }

    private Map<String, Object> buildRequestBaseOnSo(OfcSoHead so) {
        Map<String, Object> order = new HashMap<>();
        Map<String, Object> extendedProperties = so.extendedProperties();
        OfcSupplier fulfillConfig = findFulfillConfig(so);
        order.put("order_id", so.getSoBillCode());
        order.put("order_other_id", so.getOrderCode());
        order.put("order_type", 1);
        order.put("trans_time", extendedProperties.get("trans_time"));
        order.put("vender_id", so.getVenderId());
        order.put("to_vender_id", fulfillConfig.externalCooperateWith());
        order.put("owner_id", 1);
        order.put("warehouse_code", fulfillConfig.externalCooperateWarehouse());
        order.put("to_warehouse_code", so.getSupplierDc());
        order.put("order_time", so.getOrderTime());
        order.put("items", buildSoItems(so));
        return order;
    }

    private Map<String, Object> buildHeaders(OfcSoHead so) {
        Map<String, Object> headers = new HashMap<>();
        headers.put("venderId", so.getVenderId());
        return headers;
    }

    private String warehouseCode(Map<String, Object> fulfillConfig) {
        String warehouseCode = (String) fulfillConfig.get("sourceDC");
        if (StringUtils.isBlank(warehouseCode)) {
            throw new BusinessException(CommonResult.ERROR, "can not find property sourceDC in fulfill config");
        }
        return warehouseCode;
    }

    private OfcOrderHead findParentOrder(OfcSoHead so) {
        OfcOrderHead filter = new OfcOrderHead();
        filter.setOrderCode(so.getOrderCode());
        return orderService.findOne(filter, false);
    }

    private Object cooperateWith(Map<String, Object> fulfillConfig) {
        Object cooperateWith = fulfillConfig.get("cooperateWith");
        if (cooperateWith == null) {
            throw new BusinessException(CommonResult.ERROR, "can not find property cooperateWith in fulfill config");
        }
        return cooperateWith;
    }

    private List<Map<String, Object>> buildSoItems(OfcSoHead so) {
        List<Map<String, Object>> items = new ArrayList<>(so.getDetails().size());
        for (OfcSoDetail detail : so.getDetails()) {
            Map<String, Object> extendedProperties = detail.extendedProperties();
            Map<String, Object> item = new HashMap<>();
            item.put("goods_id", detail.getSkuSupplyCode());
            item.put("line_no", detail.getItemNo());
            item.put("qty", detail.getSkuOrderQty());
            item.put("unit", 1);
            item.put("is_weighing_goods", extendedProperties.get("is_weighing_goods"));
            items.add(item);
        }
        return items;
    }

    @Override
    protected boolean filterFlag(OfcTask task) {
        return false;
    }

    @Override
    protected List<OfcTask> fetchTasks(OfcTaskType type, Set<OfcTaskStatus> statuses, int shardingCount, List<Integer> shardingItems, int fetchSize) {
        return super.defaultFetchTasks(type, statuses, shardingCount, shardingItems, FETCH_SIZE);
    }
}
